package ru.pb.dao.game.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.apache.log4j.Logger;

import ru.pb.game.dao.ItemsDAO;
import ru.pb.game.data.templates.AbstractItemTemplate;
import ru.pb.game.data.xml.holders.ItemHolder;
import ru.pb.game.objects.model.inventory.ItemContainer;
import ru.pb.game.objects.model.items.Item;
import ru.pb.game.objects.storage.IStoreableObject;
import ru.pb.global.dao.annotations.DAO;
import ru.pb.global.data.model.ItemInfo;
import ru.pb.global.dbc.DatabaseFactory;
import ru.pb.global.dbc.DatabaseUtils;

/**
 * @autor: Felixx
 */
@DAO(database = "MySQL")
public class ItemsDAOImpl implements ItemsDAO
{
	private static final Logger _log = Logger.getLogger(ItemsDAOImpl.class);

	@Override
	public void select(Connection con, ItemContainer<?> container)
	{
		IStoreableObject owner = container.getOwner();
		if(owner == null)
			return;

		boolean needCloseConnection = con == null;

		PreparedStatement statement = null;
		ResultSet rset = null;

		try
		{
			if(needCloseConnection)
				con = DatabaseFactory.getInstance().newConnection();

			statement = con.prepareStatement("SELECT * FROM items WHERE owner_id=? AND (loc=? OR loc=?)");
			statement.setInt(1, owner.getObjectId());
			statement.setInt(2, container.getBaseLocation().ordinal());
			statement.setInt(3, container.getEquipLocation().ordinal());
			rset = statement.executeQuery();

			while(rset.next())
			{
				int ownerObjectId = rset.getInt("owner_id");

				int objectId = rset.getInt("object_id");

				int itemId = rset.getInt("item_id");
				int itemType = rset.getInt("item_type");
				int count = rset.getInt("count");
				int loc = rset.getInt("loc");
				int loc_slot = rset.getInt("loc_slot");
				int lifeTime = rset.getInt("life_time");
				int flags = rset.getInt("flags");

				AbstractItemTemplate itemTemplate = ItemHolder.getInstance().getTemplate(itemId);
				if(itemTemplate == null)
				{
					_log.info("Item item_id=" + itemId + " not known, object_id=" + objectId);
					continue;
				}

				if(itemTemplate.isTemporal() && rset.getInt("life_time") <= 0)
					continue;

				Item item = new Item(objectId, itemTemplate, ownerObjectId, new ItemInfo(itemId, itemType, count, loc, loc_slot, lifeTime, flags));
				container.databaseRestore(item);
			}
		}
		catch(Exception e)
		{
			_log.info("Exception: " + e, e);
		}
		finally
		{
			if(needCloseConnection)
				DatabaseUtils.closeConnection(con);

			DatabaseUtils.closeDatabaseSR(statement, rset);
		}
	}

	@Override
	public void insert(Connection con, Item item)
	{
		boolean needCloseConnection = con == null;
		PreparedStatement statement = null;
		try
		{
			if(needCloseConnection)
				con = DatabaseFactory.getInstance().newConnection();

			statement = con.prepareStatement("REPLACE INTO items (account,owner_id,item_id,item_type,count,loc,loc_slot,object_id,life_time,flags) VALUES (?,?,?,?,?,?,?,?,?,?)");
			statement.setString(1, item.getOwner().getAccount());
			statement.setInt(2, item.getOwnerObjectId());
			statement.setInt(3, item.getItemId());
			statement.setInt(4, item.getItemInfo().getItemType());
			statement.setLong(5, item.getCount());
			statement.setInt(6, item.getItemInfo().getEquippedLocation());
			statement.setInt(7, item.getItemInfo().getEquippedSlot());
			statement.setInt(8, item.getObjectId());
			statement.setInt(9, item.getLifeTimeRemainingForDatabase());
			statement.setInt(10, item.getFlags());
			statement.executeUpdate();

			item.activeDatabaseFlag(Item.EXISTS_IN_DATABASE);
			item.deactiveDatabaseFlag(Item.NEED_UPDATE);
		}
		catch(Exception e)
		{
			_log.info("Could not insert item " + item.getObjectId() + "; itemID=" + item.getItemId() + "; count=" + item.getCount() + "; owner=" + item.getOwnerObjectId() + "; exception: " + e, e);
		}
		finally
		{
			if(needCloseConnection)
				DatabaseUtils.closeConnection(con);

			DatabaseUtils.closeStatement(statement);
		}
	}

	@Override
	public void delete(Connection con, Item item)
	{
		// cancel lazy update task if need
		item.stopLazyUpdateTask(true);

		boolean needCloseConnection = con == null;
		PreparedStatement statement = null;
		try
		{
			if(needCloseConnection)
				con = DatabaseFactory.getInstance().newConnection();

			statement = con.prepareStatement("DELETE FROM items WHERE object_id = ? LIMIT 1");
			statement.setInt(1, item.getObjectId());
			statement.executeUpdate();

			item.deactiveDatabaseFlag(Item.EXISTS_IN_DATABASE);
			item.deactiveDatabaseFlag(Item.NEED_UPDATE);
		}
		catch(Exception e)
		{
			_log.info("Could not delete item " + item.getObjectId() + " in DB:", e);
		}
		finally
		{
			if(needCloseConnection)
				DatabaseUtils.closeConnection(con);

			DatabaseUtils.closeStatement(statement);
		}
	}

	@Override
	public void update(Connection con, Item item)
	{
		if( !item.isActiveDatabaseFlag(Item.NEED_UPDATE))
			return;
		boolean needCloseConnection = con == null;
		PreparedStatement statement = null;
		try
		{
			if(needCloseConnection)
				con = DatabaseFactory.getInstance().newConnection();

			statement = con.prepareStatement("UPDATE items SET account=?,owner_id=?,count=?,loc=?, loc_slot=?, life_time=?,item_id=?,flags=? WHERE object_id = ? LIMIT 1");
			statement.setString(1, item.getOwner().getAccount());
			statement.setInt(2, item.getOwnerObjectId());
			statement.setLong(3, item.getCount());
			statement.setInt(4, item.getItemInfo().getEquippedLocation());
			statement.setInt(5, item.getItemInfo().getEquippedSlot());
			statement.setInt(6, item.getLifeTimeRemainingForDatabase());
			statement.setInt(7, item.getItemId());
			statement.setInt(8, item.getFlags());
			statement.setInt(9, item.getObjectId());
			statement.executeUpdate();

			item.deactiveDatabaseFlag(Item.NEED_UPDATE);
		}
		catch(Exception e)
		{
			_log.info("Could not update item " + item.getObjectId() + " itemID " + item.getItemId() + " count " + item.getCount() + " owner " + item.getOwnerObjectId() + " in DB:", e);
		}
		finally
		{
			if(needCloseConnection)
				DatabaseUtils.closeConnection(con);

			DatabaseUtils.closeStatement(statement);
		}
	}
}